<?php
/**
 * Created by PhpStorm.
 * User: liuyu
 * Date: 2018/6/12
 * Time: 11:46
 */

namespace app\zyhsapi\model;

use app\common\lib\Aes;
use app\common\lib\exception\ApiException;
use app\common\lib\Util;
use Exception;
use think\Db;
use XznsTools\cache\zyhs\CacheManageZyhs;

/**
 * 用户档案数据操作类
 * Class Recode
 * @package app\common\model
 */
class ZyhsRecode extends BaseCacheZyhs
{
    protected $table = 'good_wechat.zyhs_recode';
    protected $cacheModel = 'recode.recode';
    protected $field = true;
    protected $userBirthCacheKey = 'recode.birth_list';

    /**
     * 获取用户一个月内所有档案的生日信息
     * @param array $user 用户信息
     * @param string $date 2020-09 或 2020-07-18
     * @param float $timezone 时区
     * @return array|bool|mixed|string
     * @throws Exception
     */
    public function userBirthMonthList($user, $date, $timezone)
    {
        $timezone = (float)($timezone ?? 8);
        $uid = $user['id'] ?? 0;
        if ($uid)
        {
            $key = $uid . '-' . date('n', strtotime($date)) . ':' . $timezone;
            //获取用户所有的档案
            $recodeData = $this->getRecodeLists($uid);
            $data = CacheManageZyhs::getInstance()->setCacheConfig($this->userBirthCacheKey, $key)
                ->getDataAndSet(function () use ($timezone, $user, $date, $recodeData)
                {
                    $self_recode = [];
                    $else_recode = [];
                    foreach ($recodeData as $recodeDatum)
                    {
                        $birth = $this->checkRecodeBirth($user, $recodeDatum, date('Y-m', strtotime($date)), $timezone);
                        if ($birth)
                        {
                            //自己的档案顺序在前
                            if ($birth['type'] == 1)
                            {
                                $self_recode[] = $birth;
                            } else
                            {
                                $else_recode[] = $birth;
                            }
                        }
                    }
                    $data = array_merge($self_recode, $else_recode);
                    return json_encode($data, true);
                });

            if (is_string($data))
            {
                $data = json_decode($data, true);
            }

        } else
        {
            $data = [];
        }
        return $data;
    }

    /**
     * 获取用户一天内所有档案的生日信息
     * @param $user
     * @param $date 2020-07-18
     * @param int $timezone
     * @return array
     * @throws Exception
     */
    public function userBirthDayList($user, string $date, int $timezone = 8)
    {
        [$year, $month, $day] = explode('-', $date);
        $nowTime = (int)((int)$month . (int)$day);
        $data = $this->userBirthMonthList($user, $date, $timezone);
        $res = [];
        foreach ($data as $datum)
        {
            $recodeTime = (int)((int)$datum['month'] . (int)$datum['day']);
            if ($recodeTime === $nowTime)
            {
                $res[] = $datum;
            }
        }
        return $res;
    }

    /**
     * 检查档案生日
     * @param array $user 用户信息
     * @param array $recode 档案信息
     * @param $date 2020-09 或 2020-07-18
     * @param float $timezone 时区
     * @return array|array[]
     * @throws Exception
     */
    public function checkRecodeBirth($user, $recode, $date, $timezone = 8)
    {
        $arr = [];
        $isYoung = $user ? $user['young_model'] : false; // 是否是青少年模式
        $astroCalendarNeedAuth = $isYoung ? 3 : 0;
        $dateArr = explode('-', $date);
        [$recode_year, $recode_month, $recode_day] = [$recode['year'], $recode['month'], $recode['day']];
//        //获取用户当前时区下的出生时间
//        $timezone = (float)($timezone ?? 8);
//        $recode_time = gmdateModify('Y-m-d', strtotimeModify('U', $recode['year'] . '-' . $recode['month'] . '-' . $recode['day']), $recode['timezone'], $timezone);
//        [$recode_year, $recode_month, $recode_day] = explode('-', $recode_time);
        $is_birth = false;

        if (count($dateArr) > 2)
        {
            [$year, $month, $day] = $dateArr;
            //判断是否今日生日
            if ($recode_month == $month && $recode_day == $day)
            {
                $is_birth = true;
            }
        } else
        {
            [$year, $month] = $dateArr;
            //判断是否本月生日
            if ($recode_month == $month)
            {
                $is_birth = true;
            }
        }
        //判断是否生日
        if ($is_birth === true)
        {
            if ($recode['isself'])
            {
                $type = 1;
                $target = 'link';
                $link = '/web/birthday/boon?need_auth=' . $astroCalendarNeedAuth . '&umeng_event_name=common_target_link&umeng_event_label=' . urlencode('生日权益页面-日历页面-领取权益');
                $btn_text = '领取权益';
                $birth = '祝可爱的你生日快乐！';
            } else
            {
                $type = 2;
                $target = 'link';
                $link = '/web/birthday/sendwish?rid=' . $recode['id'] . '&need_auth=' . $astroCalendarNeedAuth . '&umeng_event_name=common_target_link&umeng_event_label=' . urlencode('祝福好友页面-日历页面-祝福好友');
                $btn_text = '祝福好友';
                //            名称长度最长为4
                $nameLen = mb_strlen($recode['name']);
                if ($nameLen > 4)
                {
                    $name = mb_substr($recode['name'], 0, 4);
                } else
                {
                    $name = $recode['name'];
                }
                $birth = '今天是' . $name . '的生日！';
            }
            $arr = [
                'type' => $type,
                'name' => $recode['name'],
                'avatar' => $recode['avatar'],
                'text' => $birth,
                'target' => $target,
                'link' => $link,
                'btn_text' => $btn_text,
                'year' => $recode_year,
                'month' => $recode_month,
                'day' => $recode_day
            ];
        }
        return $arr;
    }

    public function cat()
    {
        return $this->belongsToMany('Cat', 'good_wechat.zyhs_recode_cat', 'cid', 'rid');
    }

    /**
     * 添加档案
     * @param $uid
     * @param $map
     * @return int|string
     * @throws Exception
     */
    public function SaveData($uid, $map)
    {
        //生成档案or_day

        //1.准币支付，免费支付，三方支付,初始化or_day为档案day
        //更新or_day
        //1.采纳生时矫正时，更新or_day为当前档案day

        $timezone = (float)(request()->header()['timezone'] ?? 8);
        try
        {
            $map['or_day'] = 0;//新增档案or_day重置0
            $id = $this->insertGetId($map);
        }
        catch (Exception $e)
        {
            $this->error = '添加失败';
            return false;
        }
//        CacheManageZyhs::getInstance()->setCacheConfig($this->cacheModel, $uid)->setListKeyType(0)->rmCache('list');
        if (isset($map['isself']) && $map['isself'] == 1)
        {
            $this->listDataAdd($uid, [$id => $id], 1);
            //删除用户缓存
            (new ZyhsUser())->updateUserinfo(['id' => $uid], ['has_self_recode' => 1]);
        } else
        {
            $this->listDataAdd($uid, [$id => $id], 0);
        }
        //清除用户档案生日信息缓存
        $key1 = $uid . '-' . (int)$map['month'] . ':' . $timezone;
        CacheManageZyhs::getInstance()->setCacheConfig($this->userBirthCacheKey, $key1)->rmCache();//清除更新月日的生日缓存
        //清除用户档案生日信息缓存
        $key2 = $uid . '-' . (int)$map['month'] . '-' . ':' . (float)($map['timezone'] ?? 8);
        CacheManageZyhs::getInstance()->setCacheConfig($this->userBirthCacheKey, $key2)->rmCache();
        return $id;
    }

    /**
     * 更新档案
     * @param $uid
     * @param $rid
     * @param array $data
     * @param int $alter_or_day
     * @return bool
     * @throws Exception
     */
    public function UpdateData($uid, $rid, $data = [], $alter_or_day = 0)
    {
        $timezone = (float)(request()->header()['timezone'] ?? 8);
        $recode = $this->getInfoById($rid, ['year', 'month', 'day', 'timezone', 'or_day']);
        if ($recode)
        {
            try
            {
                if ($alter_or_day)
                {
                    $data['or_day'] = $recode['day'];
                }
                if ($data)
                {
                    $this->allowField(true)->isUpdate(true)->save($data, ['uid' => $uid, 'id' => $rid]);
                    // 记录用户更新档案的时间
                    Db::table('good_wechat.zyhs_recode_info')->where('rid', $rid)->update(['last_time' => time()]);
                }
                //删除档案详情缓存
                CacheManageZyhs::getInstance()->setCacheConfig($this->cacheModel, $rid)->rmCache();
                if (isset($data['isself']) && $data['isself'] == 1)
                {
                    (new ZyhsUser())->removeUserCache($uid); // 删除用户缓存
                    CacheManageZyhs::getInstance()->setCacheConfig($this->cacheModel, $uid)->setListKeyType(1)->rmCache('list');
                }
            }
            catch (Exception $e)
            {
                $this->error = '更新失败';
                return false;
            }
            //当用户更新档案时间，则清除
            if (isset($data['year'], $data['month'], $data['day'], $data['timezone']))
            {
                //清除用户档案生日信息缓存
                $key1 = $uid . '-' . (int)$data['month'] . ':' . $timezone;
                CacheManageZyhs::getInstance()->setCacheConfig($this->userBirthCacheKey, $key1)->rmCache();//清除更新月日的生日缓存
            }
            $key2 = $uid . '-' . (int)$recode['month'] . ':' . (float)$recode['timezone'];
            CacheManageZyhs::getInstance()->setCacheConfig($this->userBirthCacheKey, $key2)->rmCache();//清除旧档案月日的生日缓存
        }
        return true;
    }

    /**
     * 删除档案
     * @param $uid
     * @param $map
     * @return bool
     * @throws Exception
     */
    public function DelData($uid, $rid, $map, $isself = 0)
    {
        $timezone = (float)(request()->header()['timezone'] ?? 8);
        $recode = $this->getInfoById($rid, ['year', 'month', 'day', 'timezone']);
        try
        {
            $this->where(['id' => $rid])->update($map);
        }
        catch (Exception $e)
        {
            $this->error = '删除失败';
            return false;
        }
        CacheManageZyhs::getInstance()->setCacheConfig($this->cacheModel, $uid)->setListKeyType(0)->rmCache('list');
        if ($isself == 1)
        {
            CacheManageZyhs::getInstance()->setCacheConfig($this->cacheModel, $uid)->setListKeyType(1)->rmCache('list');
        }
        CacheManageZyhs::getInstance()->setCacheConfig($this->cacheModel, $rid)->rmCache();
        //当用户删除档案时，则清除
        if (isset($recode['year'], $recode['month'], $recode['day'], $recode['timezone']))
        {
            //清除用户档案生日信息缓存
            $key1 = $uid . '-' . (int)$recode['month'] . ':' . $timezone;
            CacheManageZyhs::getInstance()->setCacheConfig($this->userBirthCacheKey, $key1)->rmCache();//清除更新月日的生日缓存
            $key2 = $uid . '-' . (int)$recode['month'] . ':' . (float)$recode['timezone'];
            CacheManageZyhs::getInstance()->setCacheConfig($this->userBirthCacheKey, $key2)->rmCache();//清除旧档案月日的生日缓存
        }
        return true;
    }

    /**
     * 获取当前用户的档案列表或用户自己的档案信息
     * @param int $uid
     * @param int $isself 0=》获取用户全部档案 1=》获取用户自己的档案
     * @return array
     * @throws Exception
     */
    public function getRecodeLists($uid, $isself = 0)
    {
        $field = ['id', 'name', 'type', 'year', 'month', 'day', 'hour', 'minute', 'timezone', 'birth_country', 'birth_province', 'birth_city', 'live_country', 'live_province', 'live_city', 'comments', 'isself', 'long_deg', 'long_min', 'ew', 'lat_deg', 'lat_min', 'ns', 'avatar', 'is_summer', 'uid', 'aid', 'sun', 'moon', 'merc', 'venu', 'mars', 'jupi', 'satu', 'non', 'lili', 'juno', 'asc', 'mc', 'or_day', 'status', 'from', 'is_read'];

        $rids = CacheManageZyhs::getInstance()->setCacheConfig($this->cacheModel, $uid)
            ->setListKeyType($isself)
            ->ZsGetIocData('list', function () use ($uid, $isself)
            {
                if ($isself)//获取用户自己的档案
                {
                    return $this->getSelfRecodeFromDms($uid);
                }
                return $this->getUserAllRecodeIdFromDms($uid);
            });

        $recode = $this->batchGetInfoByIds($rids, $field);
        array_multisort(array_column($recode, 'id'), SORT_NUMERIC, SORT_DESC, $recode);
        if ($isself == 1 && $recode)
        {
            $recode = current($recode);
        }
        return $recode;
    }

    /**
     * 数据库获取用户所有的档案id
     * @param $uid
     * @return array|bool|null
     */
    public function getUserAllRecodeIdFromDms($uid)
    {
        $where = ['uid' => $uid, 'status' => 1];
        try
        {
            $data = $this
                ->where($where)
                ->column('id', 'id');
            $data = array_flip_key_value($data);
        }
        catch (Exception $e)
        {
            $this->error = '获取档案失败';
            return false;
        }
        return $data;
    }

    /**
     * 从数据库中获取自己的档案id
     * @param $uid
     * @return bool | array
     */
    public function getSelfRecodeFromDms($uid)
    {
        try
        {
            $data = $this
                ->where(['uid' => $uid, 'isself' => 1, 'status' => 1])
                ->column('id', 'id');
            $data = array_flip_key_value($data);
        }
        catch (Exception $e)
        {
            $this->error = '获取档案失败';
            return false;
        }
        return $data;
    }

    /**
     * 数据库批量获取档案信息
     * @param array $ids
     * @return array
     * @throws ApiException
     */
    public function getInfoByIdsInData($ids, $type, $sortType)
    {
        $field = 'r.status,r.id,r.name,r.type,r.year,r.month,r.day,r.hour,r.minute,r.timezone,birth_country,birth_province,birth_city,live_country,live_province,live_city,comments,isself,long_deg,long_min,ew,lat_deg,lat_min,ns,avatar,is_summer,or_day,uid,aid,sun,moon,merc,venu,mars,jupi,satu,non,lili,juno,asc,mc,r.is_read';
        $where = ['r.id' => ['in', $ids]];
        try
        {
            $data = $this->alias('r')
                ->join('good_wechat.zyhs_recode_astro ra', 'r.aid=ra.id', 'LEFT')
                ->where($where)
                ->column($field, 'r.id');
        }
        catch (Exception $e)
        {
            throw new ApiException('档案信息获取失败', 200, config('code.error'));
        }
        return $data;
    }

    public function batchGetInfoByIds($cids, $field = [])
    {
        $resData = parent::batchGetInfoByIds($cids, $field);

        return $this->dataInit($resData);
    }

    /**
     * 数据初始化
     * @param array $data
     * @return array
     */
    public function dataInit(array $data)
    {
        foreach ($data as $index => $itemData)
        {
            $data[$index] = arrayKeyData2int($itemData, ['id', 'type', 'year', 'month', 'day', 'hour', 'minute', 'timezone', 'isself', 'long_deg', 'long_min', 'ew', 'lat_deg', 'lat_min', 'ns', 'is_summer', 'uid', 'aid', 'is_read', 'status', 'or_day']);
        }

        return $data;
    }

    /**
     * 组成档案日月升信息
     * @param array $recode
     * @return mixed
     */
    public function getRecodeAstroInfo($recode = [])
    {
        $timestamp = strtotime($recode['year'] . '-' . $recode['month'] . '-' . $recode['day'] . ' ' . $recode['hour'] . ':' . $recode['minute']);

        $timestamp -= ($recode['timezone'] + $recode['is_summer']) * 3600;

        $utdatenow = strftime('%d.%m.%Y', $timestamp);
        $utnow = strftime('%H:%M:%S', $timestamp);

        $longitude = ($recode['long_deg'] + $recode['long_min'] / 60) * $recode['ew'];
        $latitude = ($recode['lat_deg'] + $recode['lat_min'] / 60) * $recode['ns'];
        exec(config('astrolog.prefix') . " -b{$utdatenow} -ut{$utnow} -p0123456789DAmHt -eswe -house{$longitude},{$latitude},p -flj -g, -head", $out);

        if (!empty($out) || count($out) < 27)
        {
            unset($out);
            exec(config('astrolog.prefix') . " -b{$utdatenow} -ut{$utnow} -p0123456789DAmHt -eswe -house{$longitude},{$latitude},w -flj -g, -head", $out);
        }
        $planet = $planet_house = [];
        foreach ($out as $k => $line)
        {
            $row = explode(',', $line);

            $planet[$k] = @(float)$row[0];
            $planet_house[$k] = @floor($row[1]);
        }

        $result['sun'] = InWhichSign($planet[0]) . '-' . $planet_house[0] . '-' . $planet[0];
        $result['moon'] = InWhichSign($planet[1]) . '-' . $planet_house[1] . '-' . $planet[1];
        $result['asc'] = InWhichSign($planet[17]) . '-' . $planet_house[17] . '-' . $planet[17];

        return $result;
    }

    /**
     * 组合档案数据
     * @param $recode
     * @return array
     * @throws ApiException
     */
    public function recodeInfoFormat($recode)
    {
        $arr = [
            'isself' => (int)($recode['isself'] ?? 0),
            'avatar' => $recode['avatar'],
            'name' => $recode['name'],
            'recode_time' => $recode['year'] . '.' . sprintf('%02d', $recode['month']) . '.' . sprintf('%02d', $recode['day']) . ' ' . sprintf('%02d', $recode['hour']) . ':' . sprintf('%02d', $recode['minute']),
            'birth_address' => $recode['birth_country'] . $recode['birth_province'] . $recode['birth_city'],
            'live_address' => $recode['live_country'] . $recode['live_province'] . $recode['live_city'],
            'sex' => $recode['type'] == 1 ? '男' : '女'
        ];
        if ($recode['timezone'])
        {
            if ($recode['timezone'] > 0)
            {
                $arr['timezone'] = '东' . (new Util())->numberChinese($recode['timezone']) . '区 GMT+' . $recode['timezone'];
            } else
            {
                $arr['timezone'] = '西' . (new Util())->numberChinese(abs($recode['timezone'])) . '区 GMT' . $recode['timezone'];
            }
        } else
        {
            $arr['timezone'] = '中时区 GMT0';
        }
        if ($recode['birth_country'] && $recode['birth_province'] && $recode['birth_city'])
        {
            $arr['birth_address'] = $recode['birth_country'] . $recode['birth_province'] . $recode['birth_city'];
        }
        if ($recode['ew'] == 1)
        {
            $long = 'E' . $recode['long_deg'] . '°' . $recode['long_min'] . '′';
        } else
        {
            $long = 'W' . $recode['long_deg'] . '°' . $recode['long_min'] . '′';
        }

        if ($recode['ns'] == 1)
        {
            $lat = 'N' . $recode['lat_deg'] . '°' . $recode['lat_min'] . '′';
        } else
        {
            $lat = 'S' . $recode['lat_deg'] . '°' . $recode['lat_min'] . '′';
        }
        $arr['long_lat'] = $long . ' ' . $lat;
        return $arr;
    }

    /**
     * 获取档案信息字符串
     * @param $recode
     * @return string
     */
    public function getRecodeInfoStr($recode)
    {
        return $recode['type'] . $recode['year'] . $recode['month'] . $recode['day'] . $recode['hour'] . $recode['minute'] . $recode['timezone'] . $recode['is_summer'] . $recode['long_deg'] . $recode['long_min'] . $recode['ew'] . $recode['lat_deg'] . $recode['lat_min'] . $recode['ns'];
    }

    /**
     * 通过手机号  获取账号档案数量 准有好事
     * @param string $tel
     * @param int $uid
     * @return array
     * @throws Exception
     */
    public function getAccountRecodeNumByTelZyhs(string $tel, int $uid)
    {
        $userData = Db::table('wechat_backup_07_18_14_43_00.app_user')->alias('u')->where(['u.tel' => $tel])->whereOr(['u.temporary_tel' => $tel])->column('u.id,u.nickname,u.avatar', 'u.id');
        $resData = [];
        if ($userData)
        {
            $uids = array_column($userData, 'id');
            $xzUid = Db::table('wechat_backup_07_18_14_43_00.zl_user_xz')->whereIn('uid', $uids)->column('uid');
            $resUid = array_diff($uids, $xzUid);
            if ($resUid)
            {
                $resUid = array_values($resUid);
                $recodeNum = Db::table('wechat_backup_07_18_14_43_00.app_recode')->whereIn('uid', $resUid)->where('status', 1)->group('uid')->column('count(id) as num', 'uid');
                arsort($recodeNum); // 保留 key 值 对 value 进行倒序排序【大到小】
                $AesLib = new Aes();
                $newTime = time();
                foreach ($recodeNum as $uidItem => $num)
                {
                    if ($num > 0)
                    {
                        if ($userData[$uidItem]['avatar'])
                        {
                            $avatar = $userData[$uidItem]['avatar'];
                            if (!preg_match('/^http(s?):\/\/*/', $avatar))
                            {
                                $avatar = 'https://oss.goddessxzns.com/' . $avatar;
                            }
                        } else
                        {
                            $avatar = 'https://oss.goddessxzns.com/avatar_default_2.png';
                        }
                        $uidHash = random_int(1000, 9999) . '20' . $uidItem . '|' . random_int(1000, 9999) . '12' . $uid . '|' . $newTime; // 前5位为混淆字符串
                        $resData[] = [
                            'uid' => $AesLib->encryptWithOpenssl($uidHash, 'zyhsapp'),
                            'nickname' => $userData[$uidItem]['nickname'],
                            'recode_num' => $num,
                            'avatar' => $avatar,
                        ];
                    }
                }
            }
        }

        return $resData;
    }
}
